from rest_framework import serializers
from rest_framework.validators import ValidationError, UniqueTogetherValidator

from saas_main import models
from saas_main.serializer.hook_change_serializer import HookSerializer
from utils.tencent_cos import get_file_info


class ProjectSerializer(serializers.ModelSerializer):
    color_code = serializers.CharField(source='get_project_color_display', read_only=True)
    creator_name = serializers.CharField(source='creator.username', read_only=True)

    class Meta:
        model = models.Project
        fields = "__all__"
        # 对于联合唯一字段的校验以及自定义错误信息
        validators = [
            UniqueTogetherValidator(
                queryset=models.Project.objects.all(),
                fields=('project_title', 'creator'),
                message="此项目标题已经存在！"
            )
        ]


class WikiSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Wiki
        fields = "__all__"

    def validate(self, attrs):
        if parent_obj := attrs.get('parent'):
            if parent_obj.project == attrs['project']:
                return attrs
            else:
                raise ValidationError(f"当前项目中没有标题为{attrs['parent']}的上级文档")
        return attrs


class FileSerializer(serializers.ModelSerializer):
    update_user_name = serializers.CharField(source='update_user.username', read_only=True)
    update_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", required=False)
    etag = serializers.CharField(max_length=128, write_only=True,required=False)

    class Meta:
        model = models.FileRepository
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=models.FileRepository.objects.all(),
                fields=("name", "file_type", 'parent', 'project'),
                message="当前目录，创建的文件/文件夹名称已存在！"
            )
        ]

    def validate(self, attrs):
        if not attrs.get('parent'):
            if models.FileRepository.objects.filter(
                    project=attrs['project'], name=attrs['name'], file_type=attrs['file_type'], parent=None):
                raise ValidationError("根目录，创建的文件/文件夹名称已存在！")
        if attrs['file_type'] == 1 and attrs.get('key'):
            if not attrs['key'].endswith(attrs['name']):
                raise ValidationError("文件信息key错误！")
            project_obj = attrs['project']
            try:
                data = get_file_info(project_obj.bucket, project_obj.region, attrs['key'])
            except Exception:
                raise ValidationError('COS中获取文件信息失败！')
            if data.get('ETag') != attrs['etag']:
                raise ValidationError('Etag信息不匹配！')
            if int(data.get('Content-Length')) != attrs['file_size']:
                raise ValidationError('文件大小信息错误！')
        return attrs

    def create(self, validated_data):
        if validated_data['file_type'] == 1:
            validated_data.pop('etag')
        instance = super().create(validated_data)
        return instance


class IssueSerializer(HookSerializer, serializers.ModelSerializer):
    latest_update_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)

    class Meta:
        model = models.Issues
        fields = "__all__"

    def change_issues_type(self, instance):
        return instance.issues_type.title

    def change_status(self, instance):
        return instance.get_status_display()

    def change_creator(self, instance):
        return instance.creator.realname

    def change_assign(self, instance):
        if res := instance.assign:
            return res.realname
        else:
            return '未指派'

    def change_end_date(self, instance):
        if res := instance.end_date:
            return res
        else:
            return '无期限'

    def validate(self, attrs):
        if self.instance:
            pro = self.instance.project
        else:
            pro = attrs['project']
        if attrs.get('issues_type'):
            if not (pro == attrs.get('issues_type').project):
                raise ValidationError(f'错误的issues_type，不属于项目{pro}!')
        if attrs.get('module'):
            if not (pro == attrs.get('module').project):
                raise ValidationError(f'错误的module，不属于项目{pro}!')
        if attrs.get('parent'):
            if not (pro == attrs.get('parent').project):
                raise ValidationError(f'错误的parent，不属于项目{pro}!')
        if attrs.get('assign'):
            if not (models.ProjectRelation.objects.filter(
                    project=pro, user=attrs.get('assign')).exists()):
                raise ValidationError(f'错误的assign，{attrs.get("assign")}不属于项目{pro}!')
        if attrs.get('attention'):
            for user in attrs.get('attention'):
                if not (models.ProjectRelation.objects.filter(project=pro, user=user)):
                    raise ValidationError(f'错误的attention，{user}不属于项目{pro}!')
        return attrs


class IssueReplySerializer(HookSerializer, serializers.ModelSerializer):
    create_datetime = serializers.DateTimeField(format="%Y-%m-%d %H:%M:%S", read_only=True)
    creator_name = serializers.CharField(source='creator.realname', read_only=True)

    class Meta:
        model = models.IssuesReply
        fields = "__all__"

    def change_reply_type(self, instance):
        return instance.get_reply_type_display()


class InviteSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.ProjectInvite
        fields = "__all__"
